#include <ka_command.h>
#include <string.h>
#include <stdio.h>

#define TEST_SIZE 4
bool acl_matrix[TEST_SIZE][TEST_SIZE] = {0};
const TEE_UUID uuids[TEST_SIZE] = {
    {0x79b77788, 0x9789, 0x4a7a, {0xa2, 0xbe, 0xb6, 0x1, 0x55, 0xee, 0xf5, 0xf3}},
    {0x56345788, 0x9689, 0x464a, {0xa2, 0xbe, 0xd1, 0x1, 0x67, 0xee, 0xf5, 0xf2}},
    {0x79543638, 0x9749, 0x472a, {0xa2, 0xac, 0xb6, 0x1, 0x55, 0x54, 0xf5, 0xf3}},
    {0x79213558, 0x4563, 0x4168, {0x26, 0xbe, 0xb6, 0x2, 0x55, 0xee, 0x25, 0xf3}},
};
void check_acl()
{
    bool error = false;

    for (size_t i = 0; i < TEST_SIZE; i++)
    {
        for (size_t j = 0; j < TEST_SIZE; j++)
        {
            TEE_Result rc = KA_CMD_Find(uuids[i], uuids[j]);
            bool acl_valid = rc == TEE_SUCCESS;
            if (acl_valid != acl_matrix[i][j])
            {
                error = true;
                EMSG("UUID[%d] ACL error, guest[%d] is %d\n", i, j, acl_valid);
            }
        }
    }
    DMSG("Check acl %s!\n", error ? "failed" : "pass");
}

void KA_ACL_Test()
{
    DMSG("KA_ACL_Test\n");
    DMSG("Initial ACL state:\n");
    for (size_t i = 0; i < TEST_SIZE; i++)
    {
        char buf[TEST_SIZE + 1] = {0};
        for (size_t j = 0; j < TEST_SIZE; j++)
        {
            if (KA_CMD_Find(uuids[i], uuids[j]) == TEE_SUCCESS)
            {
                acl_matrix[i][j] = true;
                buf[j] = 'V';
            }
            else
            {
                acl_matrix[i][j] = false;
                buf[j] = 'I';
            }
        }
        DMSG("UUID[%d]:%s\n", i, buf);
    }

    check_acl();
    KA_CMD_Add(uuids[0], uuids[1]);
    acl_matrix[0][1] = true;
    KA_CMD_Add(uuids[0], uuids[2]);
    acl_matrix[0][2] = true;
    KA_CMD_Add(uuids[1], uuids[2]);
    acl_matrix[1][2] = true;
    KA_CMD_Add(uuids[1], uuids[0]);
    acl_matrix[1][0] = true;
    KA_CMD_Add(uuids[1], uuids[3]);
    acl_matrix[1][3] = true;
    check_acl();

    KA_CMD_Delete(uuids[1], uuids[0]);
    acl_matrix[1][0] = false;
    KA_CMD_Delete(uuids[1], uuids[3]);
    acl_matrix[1][3] = false;
    check_acl();

    KA_CMD_Add(uuids[1], uuids[0]);
    acl_matrix[1][0] = true;
    KA_CMD_Add(uuids[1], uuids[3]);
    acl_matrix[1][3] = true;
    check_acl();

    KA_CMD_Add(uuids[1], uuids[0]);
    acl_matrix[1][0] = true;
    KA_CMD_Add(uuids[1], uuids[3]);
    acl_matrix[1][3] = true;
    check_acl();

    KA_CMD_Delete(uuids[1], uuids[0]);
    acl_matrix[1][0] = false;
    KA_CMD_Delete(uuids[1], uuids[3]);
    acl_matrix[1][3] = false;
    check_acl();

    KA_CMD_Delete(uuids[1], uuids[0]);
    acl_matrix[1][0] = false;
    KA_CMD_Delete(uuids[1], uuids[3]);
    acl_matrix[1][3] = false;
    check_acl();
}

void KA_KEY_Test()
{
    uint8_t 
    n[256] = {0}, 
    e[256] = {0}, 
    d[256] = {0}, 
    p[256] = {0}, 
    q[256] = {0}, 
    dmp1[256] = {0}, 
    dmq1[256] = {0}, 
    iqmp[256] = {0};
    size_t 
    n_size = 256, 
    e_size = 256, 
    d_size = 256, 
    p_size = 256, 
    q_size = 256, 
    dmp1_size = 256, 
    dmq1_size = 256, 
    iqmp_size = 256;
    TEE_Result rc = TEE_SUCCESS;
    DMSG("KA_KEY_Test\n");
    KA_CMD_Add(uuids[0], uuids[1]);
    KA_CMD_Add(uuids[1], uuids[0]);
    for (size_t i = 0; i < 2; i++)
    {
        rc = KA_CMD_GetPrivateKey(uuids[i],
                             n, &n_size,
                             e, &e_size,
                             d, &d_size,
                             p, &p_size,
                             q, &q_size,
                             dmp1, &dmp1_size,
                             dmq1, &dmq1_size,
                             iqmp, &iqmp_size);
        if(rc) {
            EMSG("UUID[%d] rc 0x%08x\n",i,rc);
            continue;
        }
        DMSG("UUID[%d] Private Key [ n ] size : %d byte[0] : %d\n", i, n_size, n[0]);
        DMSG("UUID[%d] Private Key [ e ] size : %d byte[0] : %d\n", i, e_size, e[0]);
        DMSG("UUID[%d] Private Key [ d ] size : %d byte[0] : %d\n", i, d_size, d[0]);
        DMSG("UUID[%d] Private Key [ p ] size : %d byte[0] : %d\n", i, p_size, p[0]);
        DMSG("UUID[%d] Private Key [ q ] size : %d byte[0] : %d\n", i, q_size, q[0]);
        DMSG("UUID[%d] Private Key [ dmp1 ] size : %d byte[0] : %d\n", i, dmp1_size, dmp1[0]);
        DMSG("UUID[%d] Private Key [ dmq1 ] size : %d byte[0] : %d\n", i, dmq1_size, dmq1[0]);
        DMSG("UUID[%d] Private Key [ iqmp ] size : %d byte[0] : %d\n", i, iqmp_size, iqmp[0]);
    }
}

void KA_CMD_Test()
{
    DMSG("Begin KA_CMD_Test\n");
    KA_ACL_Test();
    KA_KEY_Test();
    DMSG("End KA_CMD_Test\n");
}
